/**
 * @file ManagerFactory.h
 * @author huangxiaozhu (xiaozhuhuang2014@163.com)
 * @brief  用于管理各个服务模块。例如：硬件电气模块，异常模块，诊断模块，数据采集模块等等。
 *         1、避免各个服务模块使用GetInstance()。
 *         2、明确各个服务模块的生命周期，和确保各个服务模块的初始化的依赖关系
 * @version 1.0.0
 * @date 2024-02-26
 * 
 * @copyright Copyright (c) 2024
 * 
 */

#pragma once

#include "BaseManager.h"
#include <list>


/**
 * @brief 维护各个模块的数据结构
 */
struct ManagerData
{
    std::string name;
    BaseManagerPtr managerPtr;
};


/**
 * @brief ManagerFactory 服务模块的总入口
 */
class ManagerFactory
{
public:
    ManagerFactory(){}
    virtual ~ManagerFactory(){}

    virtual bool InitManagers();        // 初始化各个服务模块
    virtual void DestroyManagers();     // 销毁各个服务模块

    /**
     * @brief 注册服务模块，有先后顺序，确保依赖关系没有问题
     * 
     * @tparam T        具体服务模块类型
     * @param name      名字与服务模块对象绑定。
     *                  此参数其实可以通用typeid(T).name()获得，不必通过参数传入。但是为了支持统一模块注册多个模块对象，引入此typeName的参数
     *                  对于服务模块只需要一个对象，调用此函数时候就通过typeid(T).name()设置此参数。
     * @return bool     true为注册成功，false为注册失败
     */
    template <typename T>
    bool RegisterManager(const std::string& name = typeid(T).name())
    {
        if (std::is_base_of<BaseManager, T>::value == false)
        {
            return false;
        }

        bool found = false;
        for (auto& item : m_managerList)
        {
            if (item.name == name)
            {
                found = true;
                break;
            }
        }

        if (found)      // 不允许重复注册
        {
            return false;
        }

        // 创建新对象
        auto ptr = std::make_shared<T>(name);
        if (ptr == nullptr)
        {
            return false;
        }

        ManagerData data{name, ptr};
        m_managerList.push_back(data);

        return true;
    }

    /**
     * @brief Get the Manager object
     * 
     * @tparam T 
     * @return std::shared_ptr<T> 
     */
    template <typename T>
    std::shared_ptr<T> GetManager(const std::string& name = typeid(T).name())
    {
        if (std::is_base_of<BaseManager, T>::value == false)
        {
            return nullptr;
        }

        for (auto& item : m_managerList)
        {
            if (item.name == name)
            {
                return std::dynamic_pointer_cast<T>(item.managerPtr);
            }
        }

        return nullptr;
    }



protected:
    std::list<ManagerData> m_managerList;           // 使用list就是为了保证各个模块的初始化的先后顺序依赖关系
};


// using ManagerFactoryPtr = std::shared_ptr<ManagerFactory>;

// /**
//  * @brief  Get the Manager Factory Instance object
//  * 
//  * @return ManagerFactoryPtr 
//  */
// ManagerFactoryPtr MgrFactoryInstance();